﻿using System;
using System.Collections.Generic;
using CarlosAg.ExcelXmlWriter;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Manager;

namespace SdmxMl.Excel
{
    /// <summary>
    /// Specialized class for exporting Hierarchical codelist in Excel
    /// </summary>
    public class ExcelExportHCL : ExcelExportBase
    {
        #region Internal Members

        protected Dictionary<string, CodeListType> dico;
        private HierarchicalCodelistType hcl;
        private HierarchyType hierarchy;
        private SmManager smManager;
        private int itemCount;

        #endregion

        #region C'tor

        public ExcelExportHCL(HierarchicalCodelistType h, SmManager sm)
        {
            hcl = h;
            hierarchy = hcl.HierarchyList[0];
            smManager = sm;
            dico = null;
        }
        #endregion

        #region Header

        private void GenerateHeaderNames()
        {
            headerColitems = new List<string>(16);

            headerColitems.Add("Code");
            headerColitems.Add("Parent");
            headerColitems.Add("Level");
            headerColitems.Add("Valid from");
            headerColitems.Add("Valid to");

            foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                headerColitems.Add("Name_" + lg);

            foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                headerColitems.Add("Desc_" + lg);

            anInventory = new AnnotationInventory();
            foreach (KeyValuePair<string, CodeListType> kvp in dico)
                foreach (CodeType c in kvp.Value.CodeList)
                    anInventory.Inventory(c.AnnotationList, true);

            anInventory.GenerateAnnotationHeader(headerColitems);
        }
        #endregion

        #region Overriden Export Method

        public override void Export()
        {
            // Ensure in manager
            smManager.PutArtefact(SdmxArtefactType.HierarchicalCodelists, hcl);
            ArtefactRefTypedList artl = hcl.ArtefactRefList;
            smManager.LoadMissingArtefactsFromReferenceMgr(artl);
            smManager.LoadMissingArtefactsFromRegistry(artl);

            dico = GetRefDictionary();

            GenerateBook("SMS", "OFS");
            GenerateWorksheetArtefact(hcl);
            GenerateHeaderNames();

            foreach (HierarchyType hi in hcl.HierarchyList)
            {
                hierarchy = hi;
                sheet = GenerateWorksheetHeader(
                    headerColitems.ToArray(), hierarchy.Id, hierarchy.CodeRefList.Count);

                //Must be calculated
                itemCount = 0;
                CreateRows(hierarchy.CodeRefList);

                // Update sheet count
                sheet.Table.ExpandedRowCount = 1 + itemCount;
            }
        }
        #endregion

        #region Row filling methods


        private Dictionary<string, CodeListType> GetRefDictionary()
        {
            Dictionary<string, CodeListType> dico = new Dictionary<string, CodeListType>();

            foreach (CodelistRefType crt in hierarchy.CodelistRefList)
            {
                    CodeListType clType = null;
                    Artefact a = smManager.GetArtefact(SdmxArtefactType.CodeLists, crt);
                    if (a != null)
                        clType = a as CodeListType;
                    if (clType != null)
                        dico.Add(crt.Alias, clType);
            }

            return dico;
        }


        public void CreateRows(CodeRefTypeList crtl)
        {
            itemCount += crtl.Count;
            foreach (CodeRefType it in crtl)
                FillRow(string.Empty, it, 0);
        }

        protected void FillRow(string parentCode, CodeRefType crt, int level)
        {
                CodeListType clType = dico[crt.CodelistAliasRef];
                ISdmxHierarchyListItem item = clType.CodeList.LocateItem(crt.CodeID);

                if (item == null)
                    throw new ApplicationException("Unable to proceed. Hierarchy referred code Id '" +
                        crt.CodeID + "' is not present in codelist: " + clType.FullIdent);
            WorksheetRow row = sheet.Table.Rows.Add();
            AddCell(row, crt.CodeID);
            AddCell(row, parentCode);
            AddCell(row, (level + 1).ToString());
            AddCell(row, crt.ValidFrom);
            AddCell(row, crt.ValidTo);

            foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                AddCell(row, item.Name.GetIfDefinedForLanguage(lg));

        //    MultiLang desc = item.AnnotationList.GetInternationalizedTextOfAnnotationType("NOTE");
            MultiLang desc = (item as CodeType).Description;

            if (desc != null && desc.IsEmpty == false)
            {
                foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                    AddCell(row, desc.GetIfDefinedForLanguage(lg));
            }
            else
            {
                foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                    AddCell(row, string.Empty);
            }

            // All annotations
            AddAnnotations(row, item.AnnotationList);

            // Recurse
            itemCount += crt.CodeRefList.Count;
            foreach (CodeRefType it in crt.CodeRefList)
                FillRow(crt.CodeID, it, level + 1);
        }
        #endregion

    }
}
